package com.easy.common.util.auth;
import java.io.*;
import java.util.*;

import com.easy.common.constant.Const;
import com.easy.common.exception.InvalidParamException;
import com.easy.common.util.Utility;

public class LinuxUtility {

	private static String machineCode = null;

	public LinuxUtility()
	{
	}

	public static String getMachineCode()
		throws Exception
	{
		if (machineCode == null)
		{
			LinuxUtility util = new LinuxUtility();
			machineCode = util.getMachineCodeInner();
		}
		return machineCode;
	}

	@SuppressWarnings("unchecked")
	private String getMachineCodeInner()
		throws Exception
	{
		String rtStr = null;
		Map<String, Object> diskInfoMap = parseCmdRs(exeCmd("fdisk -l"));
		if (diskInfoMap.size() > 0)
		{
			List<Map<String, Object>> partList = (List<Map<String, Object>>)diskInfoMap.get("partList");
			if (partList.size() > 0)
			{
				Map<String, Object> partMap = (Map<String, Object>)partList.get(0);
				StringBuffer rtBuf = new StringBuffer("");
				rtBuf.append("{");
				String name = Utility.null2Empty((String)partMap.get("name"));
				String boot = Utility.null2Empty((String)partMap.get("boot"));
				String start = Utility.null2Empty((String)partMap.get("start"));
				String end = Utility.null2Empty((String)partMap.get("end"));
				String block = Utility.null2Empty((String)partMap.get("block"));
				String id = Utility.null2Empty((String)partMap.get("id"));
				String system = Utility.null2Empty((String)partMap.get("system"));
				rtBuf.append((new StringBuilder("name:\"")).append(name).append("\"").toString());
				rtBuf.append((new StringBuilder(", boot:\"")).append(boot).append("\"").toString());
				rtBuf.append((new StringBuilder(", start:\"")).append(start).append("\"").toString());
				rtBuf.append((new StringBuilder(", end:\"")).append(end).append("\"").toString());
				rtBuf.append((new StringBuilder(", block:\"")).append(block).append("\"").toString());
				rtBuf.append((new StringBuilder(", id:\"")).append(id).append("\"").toString());
				rtBuf.append((new StringBuilder(", system:\"")).append(system).append("\"").toString());
				rtBuf.append("}");
				rtStr = rtBuf.toString();
			}
		}
		if (!Utility.isNullorEmpty(rtStr))
		{
			String tmpStr = DigestUtility.md5Hex(rtStr.getBytes(Const.DEFAULT_CODE));
			rtStr = (new StringBuilder(String.valueOf(tmpStr.substring(1, 3)))).append(tmpStr.substring(7, 9)).append(tmpStr.substring(20, 22)).append(tmpStr.substring(29, 31)).toString();
		} else
		{
			throw new InvalidParamException("");
		}
		return rtStr.toUpperCase();
	}

	@SuppressWarnings({ "unused", "unchecked" })
	private String appendDisInfo(Map<String, Object> diskInfoMap)
	{
		StringBuffer rtBuf = new StringBuffer("");
		String diskType = Utility.null2Empty((String)diskInfoMap.get("diskType"));
		String size = Utility.null2Empty((String)diskInfoMap.get("size"));
		String headers = Utility.null2Empty((String)diskInfoMap.get("headers"));
		String sectors = Utility.null2Empty((String)diskInfoMap.get("sectors"));
		String cylinders = Utility.null2Empty((String)diskInfoMap.get("cylinders"));
		String DiskIdentyfier = Utility.null2Empty((String)diskInfoMap.get("DiskIdentyfier"));
		rtBuf.append((new StringBuilder("diskType:\"")).append(diskType).append("\"").toString());
		rtBuf.append((new StringBuilder(", size:\"")).append(size).append("\"").toString());
		rtBuf.append((new StringBuilder(", headers:\"")).append(headers).append("\"").toString());
		rtBuf.append((new StringBuilder(", sectors:\"")).append(sectors).append("\"").toString());
		rtBuf.append((new StringBuilder(", cylinders:\"")).append(cylinders).append("\"").toString());
		rtBuf.append((new StringBuilder(", DiskIdentyfier:\"")).append(DiskIdentyfier).append("\"").toString());
		rtBuf.append(", partList:[");
		List<Map<String, Object>> partList = (List<Map<String, Object>>)diskInfoMap.get("partList");
		if (partList != null)
		{
			for (int i = 0; i < partList.size(); i++)
			{
				Map<String, Object> partMap = (Map<String, Object>)partList.get(i);
				if (i > 0)
					rtBuf.append(", ");
				rtBuf.append("{");
				String name = Utility.null2Empty((String)partMap.get("name"));
				String boot = Utility.null2Empty((String)partMap.get("boot"));
				String start = Utility.null2Empty((String)partMap.get("start"));
				String end = Utility.null2Empty((String)partMap.get("end"));
				String block = Utility.null2Empty((String)partMap.get("block"));
				String id = Utility.null2Empty((String)partMap.get("id"));
				String system = Utility.null2Empty((String)partMap.get("system"));
				rtBuf.append((new StringBuilder("name:\"")).append(name).append("\"").toString());
				rtBuf.append((new StringBuilder(", boot:\"")).append(boot).append("\"").toString());
				rtBuf.append((new StringBuilder(", start:\"")).append(start).append("\"").toString());
				rtBuf.append((new StringBuilder(", end:\"")).append(end).append("\"").toString());
				rtBuf.append((new StringBuilder(", block:\"")).append(block).append("\"").toString());
				rtBuf.append((new StringBuilder(", id:\"")).append(id).append("\"").toString());
				rtBuf.append((new StringBuilder(", system:\"")).append(system).append("\"").toString());
				rtBuf.append("}");
			}

			rtBuf.append("]");
		}
		return rtBuf.toString();
	}

	private Map<String, Object> parseCmdRs(List<String> cmdRs)
	{
		if (cmdRs == null || cmdRs.size() < 1)
			return null;
		Map<String, Object> rtMap = new HashMap<String, Object>();
		int partIndex;
		for (int startIndex = findNextNextIndex(0, cmdRs, "Disk /dev/"); startIndex >= 0; startIndex = findNextNextIndex(partIndex + 1, cmdRs, "Disk /dev/"))
		{
			String lineSize = (String)cmdRs.get(startIndex);
			String lineParam = (String)cmdRs.get(startIndex + 1);
			int diskIdIndex = findNextNextIndex(startIndex + 2, cmdRs, "Disk identifier: ");
			partIndex = findNextNextIndex(startIndex + 2, cmdRs, "Device Boot");
			if (partIndex <= startIndex)
				continue;
			partIndex = parseDiskPart(partIndex + 1, rtMap, cmdRs);
			if (rtMap.size() <= 0)
				continue;
			parseDiskSize(lineSize, rtMap);
			parseDiskParam(lineParam, rtMap);
			if (diskIdIndex > startIndex)
			{
				String lineId = (String)cmdRs.get(diskIdIndex);
				int tmpIndex = lineId.indexOf(":");
				if (tmpIndex > 0)
					rtMap.put("DiskIdentyfier", lineId.substring(tmpIndex + 1).trim());
				else
					rtMap.put("DiskIdentyfier", "");
			}
			break;
		}

		return rtMap;
	}

	private int findNextNextIndex(int currIndex, List<String> cmdRs, String token)
	{
		if (currIndex < 0 || currIndex > cmdRs.size() - 1)
			return -1;
		for (String line = (String)cmdRs.get(currIndex); currIndex < cmdRs.size(); line = (String)cmdRs.get(++currIndex))
		{
			if (line.indexOf(token) == 0)
				return currIndex;
			if (currIndex == cmdRs.size() - 1)
				break;
		}

		return -1;
	}

	private void parseDiskParam(String lineParam, Map<String, Object> rtMap)
	{
		String paramArray[] = lineParam.split(", ");
		if (paramArray != null && paramArray.length == 3)
		{
			rtMap.put("headers", paramArray[0].split(" ")[0]);
			rtMap.put("sectors", paramArray[1].split(" ")[0]);
			rtMap.put("cylinders", paramArray[2].split(" ")[0]);
		}
	}

	private void parseDiskSize(String lineSize, Map<String, Object> rtMap)
	{
		int devIndex = lineSize.indexOf("/dev/");
		int colonIndex = lineSize.indexOf(":");
		int splitIndex = lineSize.indexOf(",");
		int bytesIndex = lineSize.indexOf("bytes");
		if (colonIndex > 0 && splitIndex > 0 && bytesIndex > 0)
		{
			rtMap.put("diskType", lineSize.substring(devIndex + 5, colonIndex));
			rtMap.put("size", lineSize.substring(splitIndex + 1, bytesIndex - 1));
		}
	}

	private int parseDiskPart(int index, Map<String, Object> rtMap, List<String> cmdRs)
	{
		if (index < 0 || index > cmdRs.size() - 1)
			return index;
		String partLine = (String)cmdRs.get(index);
		List<Map<String, String>> partList = new ArrayList<Map<String, String>>();
		boolean existsBoot = false;
		for (; partLine.indexOf("/dev/") == 0; partLine = (String)cmdRs.get(index))
		{
			Map<String, String> partMap = new HashMap<String, String>();
			String wordList[] = partLine.split("\\s+");
			int firstIndex = 1;
			boolean isBoot = false;
			if (wordList.length >= 7 && wordList[1].equals("*"))
			{
				isBoot = true;
				existsBoot = true;
				firstIndex++;
			}
			partMap.put("name", wordList[0]);
			partMap.put("boot", isBoot ? "true" : "false");
			partMap.put("start", wordList[firstIndex++]);
			partMap.put("end", wordList[firstIndex++]);
			partMap.put("block", wordList[firstIndex++]);
			partMap.put("id", wordList[firstIndex++]);
			partMap.put("system", wordList[firstIndex++]);
			if (isBoot)
				partList.add(partMap);
			if (++index > cmdRs.size() - 1)
				break;
		}

		if (existsBoot)
			rtMap.put("partList", partList);
		return index;
	}

	private List<String> exeCmd(String cmd)
	{
		List<String> rtList;
		BufferedReader br;
		rtList = new ArrayList<String>();
		br = null;
		try
		{
			Process p = Runtime.getRuntime().exec(cmd);
			br = new BufferedReader(new InputStreamReader(p.getInputStream()));
			String line;
			while ((line = br.readLine()) != null) 
			{
				line = line.trim();
				rtList.add(line);
			}
		}
		catch (Exception ioexception)
		{
		}
		finally{
			try
			{
				if (br != null)br.close();
			}
			catch (Exception exception1) { }
		}
		return rtList;
	}

}
